<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
	<title>所有应用 | STAT HUB</title>
	<link type="text/css" rel="stylesheet" href="resource/css/framework.css" />
	<link type="text/css" rel="stylesheet" href="resource/css/main.css" />
	<link type="text/css" rel="stylesheet" href="resource/css/jquery.alerts.css" media="screen" />
	<script type="text/javascript" src="resource/javascript/jquery.min.js"></script>
	<script type="text/javascript" src="resource/javascript/jquery-ui.min.js"></script>
	<script type="text/javascript" src="resource/javascript/jquery.alerts.js"></script>
	<script type="text/javascript" src="resource/javascript/stathub.js"></script>
</head>
<body>
	<div class="page">
		<!--header begin-->
		<header>
			<div class="bigcontainer">
				<div id="logo">
					<a href="/">STAT HUB 应用管理</a>
				</div>
				<div class="user">
					<div class="ui compact notif menu">
						<a class="item" href="notifications.html">
							<i class="mail large icon"></i>
							<span id="message_count" class="circular floating ui small red label"></span>
						</a>
					</div>
					<div class="ui icon top right dropdown">
						<a href="user_profile.html">
							<img class="ui avatar image" src="resource/images/avatar-default.gif"/>
							欢迎，管理员
						</a>
					</div>
				</div>
			</div>
		</header>
		<!-- the main menu-->
		<div class="ui teal inverted menu">
			<div class="bigcontainer">
				<div class="right menu">
					<a class="item" href="/"><i class="home icon"></i>管理首页</a>
					<a class="item" href="node_list.html"><i class="sitemap icon"></i>节点</a>
					<a class="active item" href="app_list.html"><i class="cloud icon"></i>应用</a>
					<a class="item" href="help.html"><i class="help icon"></i>帮助</a>
					<a class="item" href="api_doc.html"><i class="info icon"></i>API接口</a>
				</div>
			</div>
		</div>
		<!--the main content begin-->
		<div class="container">
			<!--the content-->
			<div class="ui grid">
				<!--the vertical menu-->
				<div class="four wide column">
					<div class="verticalMenu">
						<div class="ui vertical pointing menu fluid">
							<a class="item" href="./new_app.html">
								<i class="rocket icon"></i> 部署新应用
							</a>
							<a class="active teal item" href="app_list.html">
								<i class="cloud icon"></i> 所有应用
							</a>
							<a class="item" href="app_stat.html">
								<i class="bar chart icon"></i> 应用统计
							</a>
						</div>
					</div>
				</div>
				<!--the App list-->
				<div class="twelve wide column">
					<div class="pageHeader">
						<div class="segment">
							<h3 class="ui dividing header">
								<i class="large cloud icon"></i>
								<div class="content">
									所有应用
									<div class="sub header">
										符合搜索条件的应用 <span id="totalCount"></span> 个，
										共 <span id="pageCount"></span> 页，这是第 <span id="pageIndex"></span> 页
									</div>
								</div>
							</h3>
						</div>
					</div>
					<div class="ui vertical segment">
						<a class="ui red small labeled icon add button" href="./new_app.html"><i class="add icon"></i>添加新应用</a>
						<div class="ui small icon input right">
							<input id="app_name" type="text" placeholder="输入应用名称搜索">
							<i id="search_button" class="search icon"></i>
						</div>
					</div>
					<div id="appList"></div>
					<div id="pagination" class="ui pagination menu"></div>
				</div>
			</div>
		</div>	
	</div>
	<!--footer begin-->
	<footer>
		<div id="copyrights">
			<div class="inset">
				<div class="bigcontainer">
					<div class="fl">
						<div class="logo"></div>
						<p>&copy; 2014 lane.cn@gmail.com <a href="https://github.com/lane-cn/stat" target="_blank">https://github.com/lane-cn/stat</a></p>
					</div>
				</div>
			</div>
		</div>
	</footer>
	<script>
	var PAGE_SIZE = 10;
	$(document).ready(function() {
		$('#search_button').click(function() {
			$("#appList").empty();
			show_apps(0);
		});
		show_apps(0);
		setInterval(function() {
			show_stats();
		}, 5000);
	});
	
	function show_apps(from) {
		$("#appList").empty();
		var query = $('#app_name').val(); 
		var size = PAGE_SIZE;
		$.get('/v1/app?query=' + encodeURIComponent(query), function(app_names, status, xhr) {
			show_pagination(app_names.length, from, size);
			for (i = 0; i < app_names.length - from && i < size; i++) {
				$("#appList").append(get_app_html(app_names[i + from]));
			}
			$.each(app_names, function(i, app_name) {
				show_app(app_name);
			});
			show_stats();
		});
	}
	
	function show_pagination(total, from, size) {
		var page_count = total % size == 0 ? total / size : Math.floor(total / size) + 1;
		var page_index = from / size + 1;
		$('#totalCount').text(total);
		$('#pageCount').text(page_count);
		$('#pageIndex').text(page_index);
		$("#pagination").empty();
		
		if (page_index == 1) {
			$('#pagination').append('<a class="icon item"><i class="icon left arrow"></i></a>');
		} else {
			$('#pagination').append('<a class="icon item" onclick="show_apps(' + (from - size) + ')"><i class="icon left arrow"></i></a>');
		}
		
		var max_pos = 3;
		var start = 1;
		var start_dis = false;
		if (page_index - start > max_pos) {
			start = page_index - max_pos;
			start_dis = true;
		}
		
		var end = page_count;
		var end_dis = false;
		if (end - page_index > max_pos) {
			end = page_index + max_pos
			end_dis = true;
		}
		
		if (start_dis) {
			$('#pagination').append('<div class="disabled item">...</div>');
		}
		
		//show page index
		for (var i=start; i<=end; i++) {
			if (i == page_index) {
				$('#pagination').append('<a class="active item">' + i + '</a>');
			} else {
				$('#pagination').append('<a class="item" onclick="show_apps(' + ((i - 1) * size) + ')">' + i + '</a>');
			}
		}
		
		if (end_dis) {
			$('#pagination').append('<div class="disabled item">...</div>');
		}

		//show next page
		if (page_index == page_count) {
			$('#pagination').append('<a class="icon item"><i class="icon right arrow"></i></a>');
		} else {
			$('#pagination').append('<a class="icon item" onclick="show_apps(' + (from + size) + ')"><i class="icon right arrow"></i></a>');
		}
	}
	
	function show_stats() {
		var app_names = get_keys();
		$.each(app_names, function(i, app_name) {
			show_stat(app_name);
		});
	}
	
	function set_button_status(app_name, start) {
		if (start) {
			$('#status_' + app_name).html('<span class="ui type label green">启动</span>');
			$('#oper_button_' + app_name).removeClass("green");
			$('#oper_button_' + app_name).addClass("black");
			$('#oper_i_' + app_name).removeClass("play");
			$('#oper_i_' + app_name).addClass("stop");
			$('#oper_s_' + app_name).text("停 止");
			$('#oper_button_' + app_name).attr('onclick', "stop_app('" + app_name + "')");
		} else {
			$('#status_' + app_name).html('<span class="ui type label black">停止</span>');
			$('#oper_button_' + app_name).addClass("green");
			$('#oper_button_' + app_name).removeClass("black");
			$('#oper_i_' + app_name).addClass("play");
			$('#oper_i_' + app_name).removeClass("stop");
			$('#oper_s_' + app_name).text("启 动");
			$('#oper_button_' + app_name).attr('onclick', "start_app('" + app_name + "')");
		}
	}
	
	function show_stat(app_name) {
		$.get('/v1/app/' + app_name, function(app, status, xhr) {
			$.get('/v1/app/' + app_name + '/choreo', function(choreo, status, xhr) {
				$.get('/v1/app/' + app_name + '/proc', function(ps, status, xhr) {
					//app status
					set_button_status(app_name, app.start);
					//instance desc
					var scale = app.start ? choreo.scale : 0;
					var inst = "";
					if (scale == 0) {
						inst += '没有计划';
					} else {
						inst += '计划 ' + scale + ' 个';
						if (choreo.dist.length > 0) {
							var distinct = new Array();
							for (var i=0; i<choreo.dist.length; i++) {
								if ($.inArray(choreo.dist[i], distinct) < 0)
									distinct.push(choreo.dist[i]);
							}
							inst += ', 在 ' + distinct.length + ' 个节点上分配 ' + choreo.dist.length + ' 个';
							if (ps.length > 0) {
								inst += ', 运行 ' + ps.length + ' 个';
							} else {
								inst += ', 没有运行';
							}
						} else {
							inst += ', 没有分配';
						}
					}
					$('#proc_' + app_name).text(inst);
					//status desc
					$('#stat_' + app_name).empty();
					if (scale == 0) {
						$('#stat_' + app_name).append('无');
					} else {
						for (var i = 0; i < scale; i ++) {
							if (i < ps.length) {
								$('#stat_' + app_name).append('<span class="ui green ok label" ></span> ');
							} else if (i < choreo.dist.length) {
								$('#stat_' + app_name).append('<span class="ui orange error label" ></span> ');
							} else {
								$('#stat_' + app_name).append('<span class="ui red error label" ></span> ');
							}
						}
					}
					//error
					if (ps.length < scale) {
						$('#error_' + app_name).show();
						$('#error_' + app_name).removeClass('hidden');
					} else {
						$('#error_' + app_name).hide();
					}
				});
			});
		});
	}
	
	function get_keys() {
		var keys = new Array();
		var ctls = $('.app_key');
		if (ctls) {
			for (var i = 0; i < ctls.length; i++) {
				var ctl = ctls[i];
				keys.push(ctl.innerHTML);
			}
		}
		return keys;
	}
	
	function get_app_html(app_name) {
		var html = '<div id="app_div_' + app_name + '" class="ui app two column middle aligned vertical grid segment">';
		html += '<div class="ui message hidden app_key">' + app_name + '</div>';
		html += '<div class="column verborder">';
		html += '<div id="error_' + app_name + '" class="ui left corner label error hidden"><div class="text">异常</div></div>';
		html += '<div class="ui info segment">';
		html += '<h5 class="ui header">' + app_name + ' <span id="status_' + app_name + '"></span></h5>';
		html += '<p>进程：<span id="proc_' + app_name + '" class="stress"></span></p>';
		html += '<p>资源：<span id="res_' + app_name + '"></span></p>';
		html += '<p>描述：<span id="desc_' + app_name + '"></span></p>';
		html += '<p>状态：<span id="stat_' + app_name + '" class="procStatus"></span></p>';
		html += '</div>';
		html += '</div>';
		html += '<div class="center aligned column">';
		html += '<div class="ui buttons">';
		html += '<a id="oper_button_' + app_name + '" class="ui tiny button"><i id="oper_i_' + app_name + '" class="icon"></i><span id="oper_s_' + app_name + '">启 动</span></a>';
		html += '<a class="ui tiny blue button" href="./app.html?name=' + app_name + '"><i class="setting icon"></i>管 理</a>';
		html += '<a class="ui tiny basic button" onclick="delete_app(\'' + app_name + '\')"><i class="trash icon"></i>删 除</a>';
		html += '</div>';
		html += '</div>';
		html += '</div>';
		return html;
	}
	
	function show_app(app_name) {
		$.get('/v1/app/' + app_name, function(app, status, xhr) {
			if (app) {
				set_button_status(app_name, app.start);
				if (app.start) {
					$('#status_' + app.name).html('<span class="ui type label green">启动</span>');
				} else {
					$('#status_' + app.name).html('<span class="ui type label black">停止</span>');
				}
				if (app.resAlloc) {
					var text = 'CPU ' + app.resAlloc.cpus + ' 核，内存 ' + byteCountToDisplaySize(app.resAlloc.mem) + '，磁盘空间 ' + byteCountToDisplaySize(app.resAlloc.disk);
					$('#res_' + app.name).html(text);
				} else {
					$('#res_' + app.name).text('不分配');
				}
				var cmd = '';
				if (app.toProcess) {
					cmd = app.toProcess + ' ';
				}
				if (app.args) {
					cmd += app.args.join(' ');
				}
				$('#desc_' + app.name).text(cmd);
			}
		});
	}
	
	function start_app(name) {
		$.post('/v1/app/' + name + '/_start', function(data, status, xhr) {
			jAlert('已经对应用 ' + name + ' 发出启动指令', '提示');
		});
	}
	
	function stop_app(name) {
		jConfirm('是否要停止应用 ' + name + ' ？', '确认', function(r) {
			if (r) {
				$.post('/v1/app/' + name + '/_stop', function(data, status, xhr) {
					jAlert('已经对应用 ' + name + ' 发出停止指令', '提示');
				});
			}
		});
	}
	
	function delete_app(name) {
		jConfirm('是否要删除应用 ' + name + ' ，这个操作无法恢复？', '确认', function(r) {
			if (r) {
				$.ajax({
					url: '/v1/app/' + name,
					type: 'DELETE',
					contentType: 'application/json',
					dataType: 'json',
					success: function(data, status, xhr) {
						$('#app_div_' + name).remove();
						jAlert('已经删除应用 ' + name, '提示');
					},
					error: function(xhr, status, error) {
						jAlert('保存失败，状态：' + error + ', 信息: ' + xhr.responseJSON.message, '提示');
					}
				});
			}
		});
	}
	</script>
</body>
</html>
